package com.example.wac.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.wac.constant.Constant;
import com.example.wac.dto.GoodsDto;
import com.example.wac.entity.Goods;
import com.example.wac.excel.InitGoodsReadListener;
import com.example.wac.mapper.GoodsMapper;
import com.example.wac.service.ExcelService;
import com.example.wac.util.EasyExcelUtils;
import com.example.wac.util.OssUtil;
import com.example.wac.vo.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author wuancheng
 * @description
 * @date 2022-01-13 15:10:00
 */

@Slf4j
@Service
public class ExcelServiceImpl implements ExcelService {

    @Autowired
    GoodsMapper goodsMapper;

    private ReentrantLock reentrantLock = new ReentrantLock();

    @Resource(name = "threadPoolTaskExecutor")
    ThreadPoolTaskExecutor executor;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public void goodsExport(HttpServletResponse response) {
        List<Goods> list = new LambdaQueryChainWrapper<>(goodsMapper)
                .list();
        EasyExcelUtils.write(response, Constant.ExcelTemplate.GOODS_EXPORT,list,"商品信息导出"+ DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN));
    }

    @Override
    public void goodsExportByPage(HttpServletResponse response) {
        // 加锁防止重复导出阻塞
        boolean flag = reentrantLock.tryLock();
        if (!flag){
            return;
        }
        InputStream inputStream = null;
        ExcelWriter excelWriter = null;
        try{
            // 配置Excel
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("商品信息导出" + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN), "UTF-8") + ".xlsx");
            inputStream = EasyExcelUtils.class.getClassLoader().getResourceAsStream(Constant.ExcelTemplate.GOODS_EXPORT);
            excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(inputStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            // 配置分页信息
            int pageNum = 0;
            int pageSize = 500;
            Page<Goods> page;
            do {
                pageNum++;
                LambdaQueryChainWrapper<Goods> wrapper = new LambdaQueryChainWrapper<>(goodsMapper);
                page = new Page<>(pageNum, pageSize);
                Page<Goods> pageActual = wrapper.page(page);
                excelWriter.write(pageActual.getRecords(),writeSheet);
            }while (page.getPages() > pageNum);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            excelWriter.finish();
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("文件输入流关闭失败", e);
                }
            }
            // 当前线程为加锁阻塞状态则释放锁
            if (reentrantLock.isHeldByCurrentThread()){
                reentrantLock.unlock();
            }
        }

    }

    @Override
    public ApiResult goodsExportOss() {
        String excelFilePath = Constant.ExcelTemplate.GOODS_EXPORT;
        String ossFilePath = "excel/"+ DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + "GoodsExportTemplate.xlsx";
        if (redisTemplate.hasKey(ossFilePath)){
            return ApiResult.error(null,"文件下载中");
        }
        List<Goods> list = new LambdaQueryChainWrapper<>(goodsMapper).list();
        executor.execute(()->{
            OssUtil.uploadExcel(excelFilePath, ossFilePath, list);
        });
        redisTemplate.opsForValue().set(ossFilePath,0,30, TimeUnit.MINUTES);
        ApiResult apiResult = OssUtil.fileFlag(ossFilePath);
        if (apiResult.getFlag()){
            return apiResult;
        }else {
            return ApiResult.error(null,"文件下载中");
        }
    }

    @Override
    public ApiResult goodsInit(HttpServletResponse response, MultipartFile file) {
        EasyExcelUtils.read(file, GoodsDto.class, new InitGoodsReadListener());
        return ApiResult.success();
    }

    @Override
    public ApiResult goodsInitByWorkbookFactory(HttpServletResponse response, MultipartFile file) {
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(file.getBytes());
            Workbook workbook = WorkbookFactory.create(byteArrayInputStream);
            // 获取第一个表格
            Sheet sheet = workbook.getSheetAt(0);
            int rowStart = 0;
            // 遍历表格的每一行
            for (Row row : sheet) {
                rowStart++;
                // 前两行为备注 跳过
                if (rowStart < 3) {
                    continue;
                }
                String name = row.getCell(0).getStringCellValue();
                String acctNo = row.getCell(1).getStringCellValue();
                String idCard = row.getCell(2).getStringCellValue();
                String mobile = row.getCell(3).getStringCellValue();
                String amount = row.getCell(4).getStringCellValue();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
